package com.chenfan.common.aspect;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;

/**
 * @Description:
 * @author: weishili
 * @date: 2021/10/14
 * @version: V1.0
 */
@Slf4j
public abstract class RetryTemplate {

    private static final int DEFAULT_RETRY_COUNT = 3;

    private int retryCount = DEFAULT_RETRY_COUNT;

    // 重试间隔时间
    private int sleepTime = 0;

    public int getSleepTime() {
        return sleepTime;
    }

    public RetryTemplate setSleepTime(int sleepTime) {
        if (sleepTime < 0) {
            throw new IllegalArgumentException("重试间隔时间不能小于0!");
        }

        this.sleepTime = sleepTime;
        return this;
    }

    public int getRetryCount() {
        return retryCount;
    }

    public RetryTemplate setRetryCount(int retryCount) {
        if (retryCount <= 0) {
            throw new IllegalArgumentException("重试次数必须大于0!");
        }

        this.retryCount = retryCount;
        return this;
    }

    /**
     * 重试的业务执行代码
     * 失败时请抛出一个异常
     *
     * @return
     */
    protected abstract Object doBiz() throws Throwable;

    public Object execute() throws InterruptedException {
        for (int i = 1; i <= retryCount; i++) {
            try {
                return doBiz();
            } catch (Throwable e) {
                log.error("重试业务执行异常: {}, 执行次数: {}", e, i);
                Thread.sleep(sleepTime * 1000);
            }
        }
        return null;
    }

    public Object submit(ExecutorService executorService) {
        if (executorService == null) {
            throw new IllegalArgumentException("异步重试业务执行异常!");
        }

        return executorService.submit((Callable) () -> execute());
    }

}
